import * as Koa from 'koa';
import { Transaction } from 'tiny-entity2';
import { Guid, route, RouteOptionsVerify, ServiceManager, Tools, UsingLock } from "../../common";
import { ServiceException } from '../../common/excpetion';
import { ApiDataContext } from '../../domain/apiDataContext';
import { AccountPermits } from '../../domain/models/accountPermits';
import { Organization } from '../../domain/models/organization';
import { Role } from '../../domain/models/role';
import { AccountPermitsService } from '../../service/accountPermitsService';
import { RoleService } from '../../service/RoleService';
const roleSvr = ServiceManager.Current.GetService<RoleService>('RoleService');
const accountPermitsSvr = ServiceManager.Current.GetService<AccountPermitsService>('AccountPermitsService');
import { OrganizationQueryParams, OrganizationService } from '../../service/organizationService';
import { AccountRolesService } from '../../service/accountRolesService';
import { UserService } from '../../service/userService';
import { User } from '../../domain/models/user';
const orgSvr = ServiceManager.Current.GetService<OrganizationService>('OrganizationService');
const accountRolesSvr = ServiceManager.Current.GetService<AccountRolesService>('AccountRolesService');
const userSvr = ServiceManager.Current.GetService<UserService>('UserService');
class RoleController {
    @route(new RouteOptionsVerify('GET', '/api/role'))
    async queryRoles(ctx: Koa.Context, next) {
        let params = ctx.query;
        let rootOrgId = ctx.headers['orgid'];
        params.organizationId=rootOrgId;
        let orgids: string[] = [];
        let result = await roleSvr.QueryRole(params);
        result.list.forEach(x => {
            if (orgids.indexOf(x.organizationId) <= -1) {
                orgids.push(x.organizationId);
            }
        });
        let orgs = await orgSvr.QueryOrganization({ ids: orgids, countOfPage: 999, pageIndex: 1 });
        result.list.forEach(x => {
            let orgobj = orgs.list.find(y => y.id == x.organizationId);
            if (orgobj) {
                x.organizationName = orgobj.name;
            }
        });
        ctx.response.body = result;
        await next();
    }
    @route(new RouteOptionsVerify('GET', '/api/role/:id'))
    async getRoleInfoById(ctx: Koa.Context, next) {
        let id = ctx.params.id;
        let role = await roleSvr.GetRoleById(id);
        let accroles = await accountRolesSvr.QueryAccountRoles({ roleId: id });
        let accids: string[] = [];
        role.users = <User[]>[];
        if (accroles && accroles.length > 0) {
            accroles.forEach(x => {
                if (accids.indexOf(x.accountId) <= -1) {
                    accids.push(x.accountId);
                }
            });
            let users = await userSvr.QueryUser({ accountIds: accids, countOfPage: 999, pageIndex: 1 });//
            role.users = users.list;
        }

        ctx.response.body = role;
        await next();
    }
    @route(new RouteOptionsVerify('POST', '/api/role'))
    async createRole(ctx: Koa.Context, next) {
        let rootOrgId = ctx.headers['orgid'];
        let role: Role = ctx.request.body;
        // role.organizationId=rootOrgId;
        checkData(role);
        let permits = role.permits;

        let result: Role = new Role();
        let permitsResult: AccountPermits[] = <AccountPermits[]>{};

        role.id = Guid.GetGuid();
        role.isDelete = false;
        role.createTime = Date.now();

        await Transaction(new ApiDataContext(), async datactx => {
            result = await roleSvr.CreateRole(role, datactx);
            for (let i = 0; i < permits.length; i++) {
                permits[i].id = Guid.GetGuid();
                permits[i].authObjectId = result.id;
                permits[i].authObjectType = result.ClassName();
                await accountPermitsSvr.CreateAccountPermits(permits[i], datactx);
                //permitsResult.find(
            }

            result.permits = permitsResult;
        });
        ctx.response.body = result;
        await next();
    }
    @route(new RouteOptionsVerify('PUT', '/api/role'))
    async updateRole(ctx: Koa.Context, next) {
        let role: Role = ctx.request.body;
        let rootOrgId = ctx.headers['orgid'];
        if (!role.id) {
            throw new ServiceException('id 不能为空！', 'not_be_null');
        }
        //role.organizationId=rootOrgId;
        checkData(role);
        let permits = role.permits;

        let result: Role = new Role();
        let permitsResult: AccountPermits[] = <AccountPermits[]>{};
        //permits
        await UsingLock(role.id, async () => {
            await Transaction(new ApiDataContext(), async datactx => {

                let roledata = await roleSvr.GetRoleById(role.id);
                roledata=Tools.ConvertToObject(role,roledata);

                result = await roleSvr.UpdateRole(roledata, datactx);

                if (permits) {
                    let delPara: AccountPermits = <AccountPermits>{ authObjectId: roledata.id, authObjectType: roledata.ClassName() };

                    await accountPermitsSvr.DeleteAccountPermits(delPara, datactx);

                    for (let i = 0; i < permits.length; i++) {
                        permits[i].id = Guid.GetGuid();
                        permits[i].authObjectId = roledata.id;
                        permits[i].authObjectType = roledata.ClassName();
                        await accountPermitsSvr.CreateAccountPermits(permits[i], datactx);//permitsResult.push(
                    }
                }

                result.permits = permitsResult;
            });
        })
        ctx.response.body = result;
        await next();
    }
    @route(new RouteOptionsVerify('DELETE', '/api/role/:id'))
    async deleteRole(ctx: Koa.Context, next) {
        let id = ctx.params.id;
        let role = await roleSvr.GetRoleById(id);
        role.isDelete = true;

        await UsingLock(role.id, async () => {
            ctx.response.body = roleSvr.UpdateRole(role);
        });

        await next();
    }
}

const checkData = (data: Role) => {
    if (!data.name) {
        throw new ServiceException('未填写角色名称！');
    }
    if (!data.organizationId) {
        throw new ServiceException('未传入根组织编号！');
    }
}